TreeviewCopyright © aleen42 all right reserved, powered by aleen42

本文转自:掘金 - RunTitan - Flutter之可滑动Widget

还有一些自己的理解

在 Android 中,如果控件超出了显示范围,会只显示一部分,而在 Flutter 中, 当内容超过显示视图时,如果没有特殊处理,Flutter 则会提示 Overflow 错误。

Flutter 提供了多种可滚动(Scrollable Widget)用于显示列表和长布局。

可滚动 Widget 都直接或间接包含一个 Scrollable, 下面是常用的几个可滚动的 Widget

  • SingleChildScrollView
  • ListView
  • GridView
  • CustomScrollView
  • 滚动监听及控制ScrollController

Scrollbar

Scrollbar 是一个 Material 风格的滚动指示器(滚动条),如果要给可滚动 widget 添加滚动条,只需将 Scrollbar 作为可滚动 widget 的父 widget 即可

  • CupertinoScrollbariOS 风格的滚动条,如果你使用的是 Scrollbar,那么在 iOS 平台它会自动切换为 CupertinoScrollbar
  • ScrollbarCupertinoScrollbar 都是通过 ScrollController 来监听滚动事件来确定滚动条位置,关于 ScrollController 详细的内容我们将在后面专门一节介绍
  • 下面是 ScrollbarCupertinoScrollbar 的构造函数, 都只有一个 child 属性, 用于接受一个可滚动的 Widget
const Scrollbar({
    Key key,
    @required this.child,
})

const CupertinoScrollbar({
    Key key,
    @required this.child,
})

示例:

      body: Scrollbar(
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Center(child: Image.asset("assets/images/icon_2.png"),),
              Center(child: Image.asset("assets/images/icon_2.png"),),
              Center(child: Image.asset("assets/images/icon_2.png"),),
              Center(child: Image.asset("assets/images/icon_2.png"),),
              Center(child: Image.asset("assets/images/icon_2.png"),),
              Center(child: Image.asset("assets/images/icon_2.png"),),
              Center(child: Image.asset("assets/images/icon_2.png"),),
              Center(child: Image.asset("assets/images/icon_2.png"),),
              Center(child: Image.asset("assets/images/icon_2.png"),),
            ],
          ),
        ),
      )

效果如下,注意屏幕右侧的滚动条:

SingleChildScrollView

SingleChildScrollView 类似于 Android 中的 ScrollView, 不再详细介绍了, 下面看一下具体使用介绍吧:

const SingleChildScrollView({
    Key key,
    this.scrollDirection = Axis.vertical,
    this.reverse = false,
    this.padding,
    bool primary,
    this.physics,
    this.controller,
    this.child,
})
  • scrollDirection,设置视图的滚动方向(默认垂直方向), 需要对应的设置其子 WidgetColumn 或者 Row, 否则会报 Overflow 错误。

  • reverse,是否按照阅读方向相反的方向滑动

    • reverse: false,则滚动内容头部和左侧对其, 那么滑动方向就是从左向右
    • reverse: true ,则滚动内容尾部和右侧对其, 那么滑动方向就是从右往左。
  • padding,内边距

  • primary,是否使用默认的 controller

  • physics,此属性接受一个 ScrollPhysics 对象,它决定可滚动 Widget 如何响应用户操作,比如用户滑动完抬起手指后,继续执行动画;或者滑动到边界时,如何显示。

    默认情况下,Flutter 会根据具体平台分别使用不同的 ScrollPhysics 对象,应用不同的显示效果,如当滑动到边界时,继续拖动的话,在 iOS 上会出现弹性效果,而在 Android 上会出现微光效果。

    如果你想在所有平台下使用同一种效果,可以显式指定,Flutter SDK 中包含了两个 ScrollPhysics 的子类可以直接使用:

    • ClampingScrollPhysics:安卓下微光效果。
    • BouncingScrollPhysicsiOS下弹性效果。
  • controller,此属性接受一个 ScrollController 对象,ScrollController 的主要作用是控制滚动位置和监听滚动事件。

    默认情况下,widget 中会有一个默认的 PrimaryScrollController,如果子 widget 中的可滚动 widget 没有显式的指定 controller 并且 primary 属性值为 true 时(默认就为true),可滚动 widget 会使用这个默认的 PrimaryScrollController,这种机制带来的好处是父 widget 可以控制子树中可滚动 widget 的滚动,例如,Scaffold 使用这种机制在 iOS 中实现了"回到顶部"的手势。

  • child,子控件。

示例:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({
    Key key,
  }) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SingleChildScrollView Demo'),
      ),
      body: Theme.of(context).platform == TargetPlatform.iOS
          ? CupertinoScrollbar(
        child: _buildListView(),
      )
          : Scrollbar(
        child: _buildListView(),
      ),
    );
  }

  Padding _buildListView() {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: SingleChildScrollView(
        child: Column(children: generatorLists(30)),
      ),
    );
  }
}

List<Widget> generatorLists(n) {
  List<Widget> lst = [];
  for (var i = 0; i < n; i++) {
    lst.add(Container(
      decoration: BoxDecoration(color: Colors.cyanAccent),
      width: double.infinity,
      height: 30,
      margin: EdgeInsets.symmetric(vertical: 8.0),
      alignment: Alignment.center,
      child: Text("${i}"),
    ));
  }
  return lst;
}

效果如下:

results matching ""

    No results matching ""